package Other;

import IceAssembly.Check;
import IceAssembly.Table;
import IceAssembly.Convert;
import IceAssembly.Control;

/**
 *Creation Date : May 9,2008.<br> 
 * <p><b>Original Author:</b>  yogesh
 */
public class Equ {
    Check check_instance = new Check();
    Table table_instance = new Table();
    Convert convert_instance = new Convert();
    
    public Equ() {
    }
    
    /**
    * This function is called whenever one of the possibilities of equ operand is a number.<p>4
    * Modified Log: None.<br>
    * May 12,2008 - Documentation changed - returns 3000 instead of 1000 - Yogesh Jindal.<br>
    * Error Condition tested: None.<br>
    * Creation Date : May 12,2008.<br>
    * Original Author: Yogesh Jindal.<br>
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param operand - operand to be processed as an integer.
    * @return Returns 0 if the operand is not an integer.<br>
    *         Returns 50 to proceed to next line.<br>
    *         Returns 3000 if symbol table out of range.<br>
    */
    private int processOne(String label ,String operand){
        if(check_instance.isInt(operand)!=1){
            return 0;
        }
        int temp=0;
        try{
            temp = Integer.parseInt(operand);
            if(temp<0 || temp>1023){
                temp = Integer.parseInt("exception");//just to cause an exception.
            }
        }catch(Exception e){
            return 0;
        }
        if(table_instance.addToSymbolTable(label, "EQU", operand)==0){
            return 3000;
        }
        return 50;
    }
            
    /**
    * This function is called whenever one of the possibilities of reset operand is a expression like
    * label+label.<p>
    * Modified Log: None.<br>
    * Error Condition tested: None.<br>
    * Creation Date : May 9,2008.<br>
    * Original Author: Yogesh Jindal.<br>
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param operand - operand to be processed as an integer.
    * @return Returns 0 if the operand is not a valid expression.<br>
    *         Returns 50 to proceed to next line.<br>
    *         Returns 1000 if error table out of range.<br> 
    */
    private int processTwo(String label ,String operand){        
        if(!(operand.contains("+")||operand.contains("-"))){
            return 0;
        }        
        if(operand.contains("+")&&operand.contains("-")){
            return 0;
        }
        if(operand.substring(0,1).contentEquals("+")||operand.substring(0,1).contentEquals("-")){
            return 0;
        }
        String op1,op2;
        if(operand.contains("+")){
            int first_plus_index = operand.indexOf("+");
            op1 = operand.substring(0, first_plus_index);
            op2 = operand.substring(first_plus_index+1);            
        }else{
            int first_minus_index = operand.indexOf("-");
            op1 = operand.substring(0, first_minus_index);
            op2 = operand.substring(first_minus_index+1);
        }
        if(op1.contentEquals("")||op2.contentEquals("")){
            return 0;
        }                
        if(check_instance.isValidLabel(op1)!=2 || check_instance.isValidLabel(op2)!=2){
            return 0;
        }
        String[] all_exvar = table_instance.getAllLabels("Exvar");
        if(!all_exvar[0].contentEquals("0")){
            for(int index=1; index<all_exvar.length; index++){
                if(op1.contentEquals(all_exvar[index]) || op2.contentEquals(all_exvar[index])){
                    return 0;
                }
            }
        }
        String lc_operand1 = table_instance.getLcOfLabel(op1);
        String lc_operand2 = table_instance.getLcOfLabel(op2);
        int lc_operand;
        if(operand.contains("+")){
            lc_operand = Integer.parseInt(lc_operand1,16)+Integer.parseInt(lc_operand2,16);
        }else{
            lc_operand = Integer.parseInt(lc_operand1,16)-Integer.parseInt(lc_operand2,16);
        }
        
        if(lc_operand>1023||lc_operand<0){
            return 0;
        }
        if(table_instance.addToSymbolTable(label, "EQU", String.valueOf(lc_operand))==0){
            return 3000;
        }
        return 50;
    }
    
    /**
    * This function is called whenever one of the possibilities of reset operand is a label.<p>
    * Modified Log: None.<br>
    * Error Condition tested: None.<br>
    * May 12,2008 - Documentation changed - returns 3000 instead of 1000 - Yogesh Jindal.<br>
    * Creation Date : May 10,2008.<br>
    * Original Author: Yogesh Jindal.<br>
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param operand - operand to be processed as an integer.
    * @return Returns 0 if the operand is not a valid label.<br>
    *         Returns 50 to proceed to next line.<br>
    *         Returns 3000 if symbol table out of range.<br>
    */
    private int processThree(String label ,String operand){
        if(check_instance.isValidLabel(operand)!=2){
            return 0;
        }
        String[] all_exvar = table_instance.getAllLabels("Exvar");
        if(!all_exvar[0].contentEquals("0")){                
            for(int index=1; index<all_exvar.length; index++){
                if(operand.contentEquals(all_exvar[index])){
                    return 0;
                }
            }
        }
        String lc_operand = table_instance.getLcOfLabel(operand);
        if(table_instance.addToSymbolTable(label, "EQU", lc_operand)==0){
            return 3000;
        }
        return 50;
    }        
    
    /**
    * This function is called whenever one of the possibilities of reset operand is a expression like
    * label+number or number+label.<p>
    * Modified Log: None.<br>
    * Error Condition tested: None.<br>
    * Creation Date : May 9,2008.<br>
    * Original Author: Yogesh Jindal.<br>
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param operand - operand to be processed as an integer.
    * @return Returns 0 if the operand is not a valid expression.<br>
    *         Returns 50 to proceed to next line.<br>
    *         Returns 1000 if error table out of range.<br> 
    */
    private int processFour(String label ,String operand){        
        if(!(operand.contains("+")||operand.contains("-"))){
            return 0;
        }        
        if(operand.contains("+")&&operand.contains("-")){
            return 0;
        }
        if(operand.substring(0,1).contentEquals("+")||operand.substring(0,1).contentEquals("-")){
            return 0;
        }
        String op1,op2;
        if(operand.contains("+")){
            int first_plus_index = operand.indexOf("+");
            op1 = operand.substring(0, first_plus_index);
            op2 = operand.substring(first_plus_index+1);            
        }else{
            int first_minus_index = operand.indexOf("-");
            op1 = operand.substring(0, first_minus_index);
            op2 = operand.substring(first_minus_index+1);
        }
        if(op1.contentEquals("")||op2.contentEquals("")){
            return 0;
        }
        int int_op1;
        int int_op2;
        if(check_instance.isInt(op1)==1 && check_instance.isValidLabel(op2)==2){
            try{
                int_op1 = Integer.parseInt(op1);
                if(int_op1>1023){
                    return 0;
                }
                String[] all_exvar = table_instance.getAllLabels("Exvar");
                if(!all_exvar[0].contentEquals("0")){
                    for(int index=1; index<all_exvar.length; index++){
                        if(op2.contentEquals(all_exvar[index])){
                            return 0;
                        }
                    }
                }
                int_op2 = Integer.parseInt(table_instance.getLcOfLabel(op2),16);
            }catch(Exception e){
                return 0;
            }        
        }else if(check_instance.isValidLabel(op1)==2 && check_instance.isInt(op2)==1){
            try{
                int_op2 = Integer.parseInt(op2);
                if(int_op2>1023){
                    return 0;
                }
                String[] all_exvar = table_instance.getAllLabels("Exvar");
                if(!all_exvar[0].contentEquals("0")){
                    for(int index=1; index<all_exvar.length; index++){
                        if(op1.contentEquals(all_exvar[index])){
                            return 0;
                        }
                    }
                }
                int_op1 = Integer.parseInt(table_instance.getLcOfLabel(op1),16);
            }catch(Exception e){
                return 0;
            }        
        }else{
            return 0;
        }
        int op_value;
        if(operand.contains("+")){
            op_value = int_op1+int_op2;
        }else{
            op_value = int_op1-int_op2;
        }
        if(op_value<0 || op_value>1023){
            return 0;
        }
        if(table_instance.addToSymbolTable(label, "EQU", String.valueOf(op_value))==0){
            return 3000;
        }
        return 50;
    }
           
    /**
    * This function is called whenever one of the possibilities of equ operand is Star notation.
     * Handles *(+or-)number and *(+or-)label.<p>
    * Modified Log: None.<br>
    * Error Condition tested: None.<br>
    * Creation Date : May 9,2008.<br>
    * Original Author: Yogesh Jindal.<br>
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param operand - operand to be processed as an integer.
    * @return Returns 0 if the operand is not a valid star notation.<br>
    *         Returns 50 to proceed to next line.<br>
    *         Returns 1000 if error table out of range.<br> 
    */
    private int processFive(String label ,String operand){
        if(operand.length()<3){
            return 0;
        }
        if(!(operand.substring(0,2).contentEquals("*+")||operand.substring(0,2).contentEquals("*-"))){
            return 0;
        }
        String star_type = operand.substring(0,2);
        operand = operand.substring(2);        
        if(check_instance.isInt(operand)==1){
            int int_code=0;
            try{
                int offset = Integer.parseInt(operand);
                if(star_type.contentEquals("*+")){
                    int_code = Control.location_counter+offset;
                }else{
                    int_code = Control.location_counter-offset;
                }
                if(int_code<0 || int_code>1023){
                    return 0;
                }
                if(table_instance.addToSymbolTable(label, "EQU", String.valueOf(int_code))==0){
                    return 3000;
                }                
            }catch(Exception e){
                return 0;
            }
        }else{
            if(check_instance.isValidLabel(operand)!=2){
                return 0;
            }
            String[] all_exvar = table_instance.getAllLabels("Exvar");
            if(!all_exvar[0].contentEquals("0")){
                for(int index=1; index<all_exvar.length; index++){
                    if(operand.contentEquals(all_exvar[index])){
                        return 0;
                    }
                }
            }
            String lc_operand = table_instance.getLcOfLabel(operand);
            int int_code = Integer.parseInt(lc_operand,16);
            if(star_type.contentEquals("*+")){
                int_code = Control.location_counter+int_code;
            }else{
                int_code = Control.location_counter-int_code;
            }
            if(int_code<0 || int_code>1023){
                return 0;
            }
            if(table_instance.addToSymbolTable(label, "EQU", String.valueOf(int_code))==0){
                return 3000;
            }                
        }                
        return 50;
    }
    
    /**
    * This function is called whenever one of the possibilities of reset operand is an expression like
    * number(+or-)number.<p>
    * Modified Log: None.<br>
    * Error Condition tested: None.<br>
    * Creation Date : May 12,2008.<br>
    * Original Author: Yogesh Jindal.<br>
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param operand - operand to be processed as an integer.
    * @return Returns 0 if the operand is not a valid expression.<br>
    *         Returns 50 to proceed to next line.<br>
    *         Returns 1000 if error table out of range.<br> 
    */
    private int processSix(String label ,String operand){        
        if(!(operand.contains("+")||operand.contains("-"))){
            return 0;
        }        
        if(operand.contains("+")&&operand.contains("-")){
            return 0;
        }
        if(operand.substring(0,1).contentEquals("+")||operand.substring(0,1).contentEquals("-")){
            return 0;
        }
        String op1,op2;
        if(operand.contains("+")){
            int first_plus_index = operand.indexOf("+");
            op1 = operand.substring(0, first_plus_index);
            op2 = operand.substring(first_plus_index+1);            
        }else{
            int first_minus_index = operand.indexOf("-");
            op1 = operand.substring(0, first_minus_index);
            op2 = operand.substring(first_minus_index+1);
        }
        if(op1.contentEquals("")||op2.contentEquals("")){
            return 0;
        }        
        if(check_instance.isInt(op1)==0 && check_instance.isInt(op2)==0){
            return 0;
        }
        int op_value=0;
        try{
            int int_op1 = Integer.parseInt(op1);
            int int_op2 = Integer.parseInt(op2);
            if(int_op1>1023 || int_op2>1023){
                return 0;
            }
            if(operand.contains("+")){
                op_value = int_op1+int_op2;
            }else{
                op_value = int_op1-int_op2;
            }
            if(op_value>1023 || op_value<0){
                return 0;
            }
        }catch(Exception e){
            return 0;
        }
        
        if(table_instance.addToSymbolTable(label, "EQU", String.valueOf(op_value))==0){
            return 3000;
        }
        return 50;
    }
    
    /**
     * This function is the main function of this class. This function calls process 1 to 6 to check all the
     * types of adc operand.
     * @param label
     * @param operand
     * @return Returns 50 to proceed to next line.<br>
     *         Returns 1000 if error table out of range.<br>
     *         Returns 2000 if intermediate file out of range.<br>
     */
    public int processEqu(String label, String operand){
        int is_blank=0;
        if(operand.contentEquals("")){//no operands.
            is_blank=1;
        }
        
        if(is_blank==0){
            operand = operand.replace(" *", "*"); operand = operand.replace("* ", "*");
            operand = operand.replace(" +", "+"); operand = operand.replace("+ ", "+");
            operand = operand.replace(" -", "-"); operand = operand.replace("- ", "-");
            operand = operand.replace(" /", "/"); operand = operand.replace("/ ", "/");

            int ret_value;
            ret_value = processOne(label,operand);
            if(ret_value!=0){
                return ret_value;
            }

            ret_value = processTwo(label,operand);
            if(ret_value!=0){
                return ret_value;
            }

            ret_value = processThree(label,operand);
            if(ret_value!=0){
                return ret_value;
            }

            ret_value = processFour(label,operand);
            if(ret_value!=0){
                return ret_value;
            }

            ret_value = processFive(label,operand);
            if(ret_value!=0){
                return ret_value;
            }

            ret_value = processSix(label,operand);
            if(ret_value!=0){
                return ret_value;
            }
        }
                
        if(table_instance.addToErrorTable("161")==0){
            return 1000;//fatal error more than 3072 errors
        }
        
        if(table_instance.addToSymbolTable(label, "EQU", "0")==0){
            return 2000;
        }                
        return 50;
    }
}